<?php

/**
 * Erra_Core_Kernel - Framework kernel
 *
 * @package
 * @author Alexis Eric
 * @copyright Copyright (c) 2012 - Erra Prod
 * @version $1.0$
 * @access public
 */

use Erra\Core\HtmlStream;

class Erra_Core_Kernel {

    public static function debug_string_backtrace() {
        ob_start();
        debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
        $trace = ob_get_contents();
        ob_end_clean();
        // Remove first item from backtrace as it's this function which is redundant.
        $trace = preg_replace('/^#0\s+' . __FUNCTION__ . "[^\n]*\n/", '', $trace, 1);
        // Renumber backtrace items.
        $trace = preg_replace('/^#(\d+)/me', '\'#\' . ($1 - 1)', $trace);
        $trace = explode("#", $trace);
        unset($trace[0]);
        unset($trace[1]);
        unset($trace[2]);
        // Don't trace error handler in call stack
        foreach ($trace as $key => &$value) {
            if (strstr($value, 'Erra_Core_Kernel::errorHandler') !== FALSE) {
                unset($trace[$key]);
            } else {
                $value = strstr($value, ' ');
            }
        }
        return $trace;
    }

    public static function fatalError($string, $display_stack_trace=true) {
        echo '<style>';
        echo '.erra-kernel-error-head-td { border-radius:10px 10px 0px 0px; }';
        echo '.erra-kernel-error-table td {border-bottom:1px solid grey; padding:5px; }';
        echo '</style>';
        echo '<table class="erra-kernel-error-table" cellspacing="0">';
        echo '<tr><td  class="erra-kernel-error-head-td"  style="font-family:Arial; background-color: #cc0000; color: #fce94f; font-size: 16px; font-weight:bold; padding:10px;">';
        echo '<span style="background-color: #cc0000; color: #fce94f;">( ! )</span>';
        echo '&nbsp;&nbsp;&nbsp;' . $string;
        echo '</td></tr>';
        if ($display_stack_trace == true) {
            $debug_backtrace = self::debug_string_backtrace();
            echo '<tr><td style="font-family:Arial; padding:4px; background-color:#eeeeec; font-size: 14px; font-weight:bold;">Call stack</td></tr>';
            foreach ($debug_backtrace as $call) {
                echo '<tr><td style="font-family:Arial;  background-color:#eeeeec; font-size: 14px;">' . $call . '</td></tr>';
            }
        }
        echo '</table>';
        exit();
    }

    /**
     * Erra_Core_Kernel::errorHandler() - Main error handler
     *
     * @param mixed $errno
     * @param mixed $errstr
     * @param mixed $errfile
     * @param mixed $errline
     * @param mixed $errcontext
     * @return
     */
    public static function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) {

        if ($errno == E_NOTICE || $errno == E_STRICT) {
            if (!$GLOBALS['ERROR_HANDLE_NOTICE']) {
                return false;
            }
        }
        // We can convert any php message to fatal error
        $fatal_error = false;
        $fatal_error_messages = array('require_once', 'Fatal error');

        foreach ($fatal_error_messages as $fatal_error_msg) {
            if (strstr($errstr, $fatal_error_msg) !== FALSE) {
                $fatal_error = true;
            }
        }

        if ($errno == E_USER_ERROR || $errno == E_ERROR || $fatal_error == true) {
            if (config_get('debug.log_messages') == 0) {
                self::fatalError(__('This page cannot be displayed due to a fatal error'), false);
            } else {
                Erra_Core_Kernel::log($errstr . ' in ' . $errfile . ' at line ' . $errline, 'error');
                self::fatalError($errstr . ' <br/><br/><span style="font-size:15px;"><i>File : ' . $errfile . '<br/>Line : ' . $errline . '</i></span>');
            }
        }

        return Erra_Core_Kernel::log($errstr . ' in ' . $errfile . ' at line ' . $errline, 'error');
    }

    /**
     * Erra_Core_Kernel::log() - Logs a message
     *
     * @param mixed $message
     * @param string $level
     * @return
     */
    public static function log($message, $level = '') {
        $firebuglite_enable = config_get('debug.firebug_lite');
        if (config_get('debug.log_messages') == 1) {
            if (function_exists('fb')) {
                if ($level == 'error') {
                    FB::log($message, null, FirePHP::ERROR);
                    if ($firebuglite_enable == true) {
                        HtmlStream::$firebugLiteStack .= '<script type="text/javascript">console.error("' . htmlspecialchars($message, ENT_QUOTES) . '")</script>' . "\n";
                    }
                } else if ($level == 'warning') {
                    if ($firebuglite_enable == true) {
                        HtmlStream::$firebugLiteStack .= '<script type="text/javascript">console.warn("' . htmlspecialchars($message, ENT_QUOTES) . '")</script>' . "\n";
                    }
                    FB::log($message, null, FirePHP::ERROR);
                } else if ($level == 'info') {
                    if ($firebuglite_enable == true) {
                        HtmlStream::$firebugLiteStack .= '<script type="text/javascript">console.info("' . htmlspecialchars($message, ENT_QUOTES) . '")</script>' . "\n";
                    }
                    FB::log($message, null, FirePHP::INFO);
                } else {
                    if ($firebuglite_enable == true) {
                        HtmlStream::$firebugLiteStack .= '<script type="text/javascript">console.log("' . htmlspecialchars($message, ENT_QUOTES) . '")</script>' . "\n";
                    }
                    FB::log($message);
                }
            }
        }
    }

    /**
     * Erra_Core_Kernel::set_memory() - Sets memory
     *
     * @param mixed $memory
     * @return
     */
    public static function set_memory($memory) {
        $old = ini_get('memory_limit');
        if (function_exists('ini_set')) {
            $memory = self::mem_to_str($memory);
            ini_set('memory_limit', $memory);
        }
        return $old;
    }

    /**
     * Erra_Core_Kernel::startSession() - Starts main session
     *
     * @param mixed $time
     * @return
     */
    public static function startSession($time = null) {
        if (is_null($time)) {
            session_set_cookie_params(0, '/');
        } else {
            session_set_cookie_params($time, '/');
        }

        if (defined('SESSION_SAVE_PATH')) {
            session_save_path(SESSION_SAVE_PATH);
        }

        if (function_exists('ini_set')) {
            ini_set('gc_maxlifetime', max($time, 7200));
            ini_set('session.gc_maxlifetime', max($time, 7200));
            ini_set('gc_probability', 1);
            ini_set('session.gc_probability', 1);
            ini_set('gc_divisor', 1000);
            ini_set('session.gc_divisor', 1000);
        }
        if (isset($_GET[session_name()])) {
            session_id($_GET[session_name()]);
        }
        session_start();
    }

    /**
     * Erra_Core_Kernel::mem_to_str() - Transforms memory to string
     *
     * @param mixed $memory
     * @return
     */
    public static function mem_to_str($memory) {
        if (is_numeric($memory)) {
            $memory = Erra_Core_File::size($memory);
        }
        return str_replace(' ', '', trim($memory, 'B'));
    }

    /**
     * Erra_Core_Kernel::setErrorHandler() - Handles error
     *
     * @param mixed $handle_notice
     * @return
     */
    public static function setErrorHandler($handle_notice = true) {
        $GLOBALS['ERROR_HANDLE_NOTICE'] = $handle_notice;
        ini_set('html_errors', '0');
        set_error_handler(array('Erra_Core_Kernel', 'errorHandler'));
    }

}

?>